package com.zhouchao.rpc.consumer.proxy;

import com.alibaba.fastjson.JSON;
import com.zhouchao.register.strategy.IRule;
import com.zhouchao.register.strategy.MinCastTimeRule;
import com.zhouchao.register.strategy.RoundRule;
import com.zhouchao.register.zookeeper.ZookeeperRegisterManager;
import com.zhouchao.rpc.common.RpcRequest;
import com.zhouchao.rpc.common.RpcResponse;
import com.zhouchao.rpc.common.Server;
import com.zhouchao.rpc.consumer.client.RpcClient;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Proxy;
import java.util.UUID;

/**
 * @Author: zhouchao
 * @Date: 2021/08/01 01:08
 * @Description:
 */
@Slf4j
public class RpcClientProxy {

    private static IRule rule = new MinCastTimeRule();

    private static final ZookeeperRegisterManager REGISTER_MANAGER = new ZookeeperRegisterManager();


    public static <T> T createProxy(Class serviceClass) {
        Object object = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{serviceClass}, (proxy, method, args) -> {
                    RpcRequest rpcRequest = new RpcRequest();
                    rpcRequest.setRequestId(UUID.randomUUID().toString());
                    rpcRequest.setClassName(method.getDeclaringClass().getName());
                    rpcRequest.setMethodName(method.getName());
                    rpcRequest.setParameterTypes(method.getParameterTypes());
                    rpcRequest.setParameters(args);

                    Server server = rule.choose();
                    if (server == null) {
                        throw new RuntimeException("没有可用的服务");
                    }
                    log.info("访问服务器：{}", server);
                    RpcClient rpcClient = new RpcClient(server.getIp(), server.getPort());

                    try {
                        long startTime = System.currentTimeMillis();
                        Object responseMsg = rpcClient.send(JSON.toJSONString(rpcRequest));
                        long endTime = System.currentTimeMillis();
                        server.setReportTime(endTime);
                        server.setCastTime(endTime - startTime);
                        //上报服务状态
                        REGISTER_MANAGER.reportServer(server);

                        RpcResponse rpcResponse = JSON.parseObject(responseMsg.toString(), RpcResponse.class);
                        if (rpcResponse.getError() != null) {
                            throw new RuntimeException(rpcResponse.getError());
                        }
                        //4.返回结果
                        Object result = rpcResponse.getResult();
                        return JSON.parseObject(result.toString(), method.getReturnType());
                    } catch (Exception e) {
                        throw e;
                    } finally {
                        rpcClient.close();
                    }
                });
        return (T) object;
    }
}
